export type PoolCallback = (obj: any) => void;
export type ObjConstructor<T> = new (...args: any[]) => T;
export type ConstructorFunction<T> = (...args: any[]) => T;

/**
 * 对象池
 */
export class Pool<T> {
    private _pool: T[] = [];
    private _objConstructor: ObjConstructor<T> | ConstructorFunction<T>;
    // 新建一个对象时的回调
    public onNew: PoolCallback = null;
    // 从对象池中弹出对象时的回调
    public onPop: PoolCallback = null;
    // 将对象压入对象池中时的回调
    public onPut: PoolCallback = null;
    // 对象释放时的回调
    public onRelease: PoolCallback = null;

    constructor(objConstuctor: ObjConstructor<T> | ConstructorFunction<T>, onGet: PoolCallback = null, onPut: PoolCallback = null, onNew: PoolCallback = null, onRelease: PoolCallback = null) {
        this._objConstructor = objConstuctor;
        this.onPop = onGet;
        this.onPut = onPut;
        this.onNew = onNew;
        this.onRelease = onRelease;
    }

    /** 从对象池中弹出对象 */
    public get(...args: any[]): T {
        let target: T = this._pool.pop();
        if (target == undefined) {
            if (typeof this._objConstructor == "function") {
                target = (this._objConstructor as ConstructorFunction<T>)(...args);
            } else {
                target = new (this._objConstructor as ObjConstructor<T>)(...args);
            }
            if (this.onNew) {
                this.onNew(target);
            }
        }

        if (this.onPop) {
            this.onPop(target);
        }

        return target;
    }

    /** 将对象压入对象池 */
    public put(obj: T) {
        this._pool.push(obj);
        if (this.onPut) {
            this.onPut(obj);
        }
    }

    /** 清空对象池 */
    public clear() {
        if (this.onRelease) {
            let target: T = null;
            while (target = this._pool.pop()) {
                this.onRelease(target);
            }

            return;
        }

        this._pool = [];
    }
}